\subsubsection{x86}

\myparagraph{x86 + MSVC}

Имеем в итоге функцию \TT{f\_signed()}:

\lstinputlisting[caption=\NonOptimizing MSVC 2010,style=customasmx86]{patterns/07_jcc/simple/signed_MSVC.asm}

\myindex{x86!\Instructions!JLE}
Первая инструкция \JLE значит \IT{Jump if Less or Equal}. 
Если второй операнд больше первого или равен ему, произойдет переход туда, где будет следующая проверка.

А если это условие не срабатывает (то есть второй операнд меньше первого), то перехода не будет, 
и сработает первый \printf.

\myindex{x86!\Instructions!JNE}
Вторая проверка это \JNE: \IT{Jump if Not Equal}.
Переход не произойдет, если операнды равны.

\myindex{x86!\Instructions!JGE}
Третья проверка \JGE: \IT{Jump if Greater or Equal} --- переход 
если первый операнд больше второго или равен ему.
Кстати, если все три условных перехода сработают, ни один \printf не вызовется. 
Но без внешнего вмешательства это невозможно.

Функция \TT{f\_unsigned()} точно такая же, за тем исключением, что используются инструкции 
\JBE и \JAE вместо \JLE и \JGE:

\lstinputlisting[caption=GCC,style=customasmx86]{patterns/07_jcc/simple/unsigned_MSVC.asm}

\myindex{x86!\Instructions!JBE}
\myindex{x86!\Instructions!JAE}
Здесь всё то же самое, только инструкции условных переходов немного другие:

\JBE --- \IT{Jump if Below or Equal} и \JAE\EMDASH{}\IT{Jump if Above or Equal}.
Эти инструкции (\JA/\JAE/\JB/\JBE) 
отличаются от \JG/\JGE/\JL/\JLE тем, что работают с беззнаковыми переменными.

\myindex{x86!\Instructions!JA}
\myindex{x86!\Instructions!JB}
\myindex{x86!\Instructions!JG}
\myindex{x86!\Instructions!JL}
\myindex{Signed numbers}
Отступление: смотрите также секцию о представлении знака в числах ~(\myref{sec:signednumbers}).
Таким образом, увидев где используется \JG/\JL вместо \JA/\JB и наоборот, 
можно сказать почти уверенно насчет того, 
является ли тип переменной знаковым (signed) или беззнаковым (unsigned).

Далее функция \main, где ничего нового для нас нет:

\lstinputlisting[caption=\main,style=customasmx86]{patterns/07_jcc/simple/main_MSVC.asm}

\input{patterns/07_jcc/simple/olly_RU.tex}

\clearpage
\myparagraph{x86 + MSVC + Hiew}
\myindex{Hiew}

Можем попробовать модифицировать исполняемый файл так, чтобы функция \TT{f\_unsigned()} всегда показывала \q{a==b},
при любых входящих значениях.
Вот как она выглядит в Hiew:

\begin{figure}[H]
\centering
\myincludegraphics{patterns/07_jcc/simple/hiew_unsigned1.png}
\caption{Hiew: функция \TT{f\_unsigned()}}
\label{fig:jcc_hiew_1}
\end{figure}

Собственно, задач три:
\begin{itemize}
\item заставить первый переход срабатывать всегда;
\item заставить второй переход не срабатывать никогда;
\item заставить третий переход срабатывать всегда.
\end{itemize}

Так мы направим путь исполнения кода (code flow) во второй \printf,
и он всегда будет срабатывать и выводить на консоль \q{a==b}.

Для этого нужно изменить три инструкции (или байта):

\begin{itemize}
\item Первый переход теперь будет \JMP, но смещение перехода 
(\gls{jump offset}) останется прежним.

\item Второй переход может быть и будет срабатывать иногда, но в любом случае он будет совершать переход
только на следующую инструкцию, потому что мы выставляем смещение перехода (\gls{jump offset}) в 0.

В этих инструкциях смещение перехода просто прибавляется к адресу следующей инструкции.

Когда смещение 0, переход будет на следующую инструкцию.

\item Третий переход конвертируем в \JMP точно так же, как и первый, он будет срабатывать всегда.

\end{itemize}

\clearpage
Что и делаем:

\begin{figure}[H]
\centering
\myincludegraphics{patterns/07_jcc/simple/hiew_unsigned2.png}
\caption{Hiew: модифицируем функцию \TT{f\_unsigned()}}
\label{fig:jcc_hiew_2}
\end{figure}

Если забыть про какой-то из переходов, то тогда будет срабатывать несколько вызовов \printf, 
а нам ведь нужно чтобы исполнялся только один.

\myparagraph{\NonOptimizing GCC}

\myindex{puts() вместо printf()}
\NonOptimizing GCC 4.4.1 производит почти такой же код, за исключением \puts~(\myref{puts}) вместо \printf.

\myparagraph{\Optimizing GCC}

Наблюдательный читатель может спросить, зачем исполнять \CMP так много раз,
если флаги всегда одни и те же?
По-видимому, оптимизирующий MSVC не может этого делать, но GCC 4.8.1 делает больше оптимизаций:

\lstinputlisting[caption=GCC 4.8.1 f\_signed(),style=customasmx86]{patterns/07_jcc/simple/GCC_O3_signed.asm}

% should be here instead of 'switch' section?
Мы здесь также видим \TT{JMP puts} вместо \TT{CALL puts / RETN}.
Этот прием описан немного позже: \myref{JMP_instead_of_RET}.

Нужно сказать, что x86-код такого типа редок.
MSVC 2012, как видно, не может генерировать подобное.
С другой стороны, программисты на ассемблере прекрасно осведомлены о том,
что инструкции \TT{Jcc} можно располагать последовательно.

Так что если вы видите это где-то, имеется немалая вероятность, что этот фрагмент кода был написан вручную.

Функция \TT{f\_unsigned()} получилась не настолько эстетически короткой:

\lstinputlisting[caption=GCC 4.8.1 f\_unsigned(),style=customasmx86]{patterns/07_jcc/simple/GCC_O3_unsigned_RU.asm}

Тем не менее, здесь 2 инструкции \TT{CMP} вместо трех.

Так что, алгоритмы оптимизации GCC 4.8.1, наверное, ещё пока не идеальны.
